use serde::{Deserialize, Serialize};
use serde_json;
use std::fs;
use std::error::Error;  // 添加这行
// use std::collections::HashMap;

// pub fn check_id_card(id_card_no: &str) -> String {
//     todo!()
// }

// 先校验，然后匹配

fn calculate_check_code(id_17: &str) -> char {
    let weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    let check_codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
    
    let sum: i32 = id_17.chars()
        .take(17)
        .enumerate()
        .map(|(i, c)| {
            let num = c.to_digit(10).unwrap() as i32;
            num * weight[i]
        })
        .sum();

    check_codes[(sum % 11) as usize]
}

fn check_18_digit(id_card_no: &str) -> String {
    // 18位身份证的位权值
    let weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
    let mut sum = 0;

    // 计算加权和
    for (i, ch) in id_card_no.chars().enumerate() {
        let value = match ch {
            'x' | 'X' => 10,
            '0'..='9' => ch.to_digit(10).unwrap() as i32,
            _ => return "身份证号码错误".to_string()
        };
        sum += weight[i] * value;
    }

    // 判断校验码
    if sum % 11 == 1 {
        id_card_no.to_string() 
    } else {
        format!("身份证号码错误: {}", id_card_no)
    }
}

fn check_15_digit(id_card_no: &str) -> String {
    // 验证15位身份证的基本格式
    if !id_card_no.chars().all(|c| c.is_ascii_digit()) {
        return "身份证号码错误".to_string();
    }

    // 提取年月日
    let year = format!("19{}", &id_card_no[6..8]);
    let month = &id_card_no[8..10];
    let day = &id_card_no[10..12];

    // 简单的日期验证
    let year_num = year.parse::<i32>().unwrap();
    let month_num = month.parse::<i32>().unwrap();
    let day_num = day.parse::<i32>().unwrap();

    if year_num < 1900 || year_num > 2000 ||
       month_num < 1 || month_num > 12 ||
       day_num < 1 || day_num > 31 {
        return "身份证号码错误".to_string();
    }

    // 转换为18位身份证号码
    let mut id_18 = String::with_capacity(18);
    id_18.push_str(&id_card_no[0..6]);  // 地区码
    id_18.push_str(&year);              // 年份，由19xx变为19xx
    id_18.push_str(&id_card_no[8..15]); // 月日和序列号
    
    // 计算校验码
    let check_code = calculate_check_code(&id_18);
    id_18.push(check_code);
    id_18
    // println!("转换后的18位身份证号码: {}", id_18);
    // format!("有效的15位身份证号码\n对应的18位身份证号码为: {}", id_18)
}


pub fn check_id_card(id_card_no: &str) -> String {
    // 位权值数组
    let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
    
    // 验证输入长度
    let processed_id = match id_card_no.len() {
        18 => check_18_digit(id_card_no),
        15 => check_15_digit(id_card_no), // 直接返回转换后的18位号码
        _ => return "身份证号码错误".to_string()
    };

    // 计算加权和
    let mut sum = 0;
    for (i, ch) in processed_id.chars().enumerate() {
        if i >= 18 { break; }
        
        let value = match ch {
            'x' | 'X' => 10,
            '0'..='9' => ch.to_digit(10).unwrap() as i32,
            _ => return "身份证号码错误".to_string()
        };
        
        sum += weights[i] * value;
    }

    // 判断是否满足条件 (sum % 11 == 1)
    if sum % 11 == 1 {
        let gender = parse_gender(&processed_id);
        let birth_date = parse_birth_date(&processed_id);
        let location = parse_location(&processed_id);  // 现在返回 String
        
        format!("身份证号码正确,{},{},{}", gender, birth_date, location)
    } else {
        "身份证号码错误".to_string()
    }
}

fn parse_gender(id_card_no: &str) -> &'static str {
    let gender_code = id_card_no.chars().nth(16)
        .and_then(|c| c.to_digit(10))
        .unwrap_or(0);
    
    if gender_code % 2 == 0 { "女" } else { "男" }
}

fn parse_birth_date(id_card_no: &str) -> String {
    let year = &id_card_no[6..10];
    let month = &id_card_no[10..12];
    let day = &id_card_no[12..14];
    
    // 简单的日期验证
    if let (Ok(y), Ok(m), Ok(d)) = (
        year.parse::<u32>(),
        month.parse::<u32>(),
        day.parse::<u32>()
    ) {
        if is_valid_date(y, m, d) {
            return format!("{}年{}月{}日", year, month, day);
        }
    }
    "无效日期".to_string()
}

fn is_valid_date(year: u32, month: u32, day: u32) -> bool {
    if month < 1 || month > 12 || day < 1 || day > 31 {
        return false;
    }
    
    let days_in_month = match month {
        4 | 6 | 9 | 11 => 30,
        2 => if is_leap_year(year) { 29 } else { 28 },
        _ => 31
    };
    
    day <= days_in_month
}

fn is_leap_year(year: u32) -> bool {
    (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
}

// ---------------------------找省份----------------------------------
#[derive(Serialize, Deserialize, Debug)]
struct Province {
    code: String,
    name: String,
    province: String,
}

fn find_province_by_code(code: &str) -> Result<String, Box<dyn Error>> {
    // 读取文件内容
    let json_str = fs::read_to_string("province.json")?;
    
    // 解析 JSON
    let provinces: Vec<Province> = serde_json::from_str(&json_str)?;
    
    // 查找匹配的省份
    let province_name = provinces
        .iter()
        .find(|p| p.province == code)  // 查找 province 字段匹配的记录
        .map(|p| p.name.clone())  // 如果找到，获取名称
        .unwrap_or_else(|| "未知省份".to_string());  // 如果未找到，返回默认值
    
    Ok(province_name)
}

// ------------------------找城市----------------------------
#[derive(Serialize, Deserialize, Debug, Clone)]
struct City {
    code: String,
    name: String,
    province: String,
    city: String,
}

fn find_city_by_code(code: &str) -> Result<String, Box<dyn Error>> {
    // 读取文件内容
    let json_str = fs::read_to_string("city.json")?;
    
    // 解析 JSON
    let cities: Vec<City> = serde_json::from_str(&json_str)?;
    
    // 查找匹配的城市
    let city_name = cities
        .iter()
        .find(|c| c.code == code)
        .map(|c| c.name.clone())
        .unwrap_or_else(|| "未知省份".to_string());
    
    Ok(city_name)
}

// 匹配地区
#[derive(Serialize, Deserialize, Debug, Clone)]
struct District {
    code: String,
    name: String,
    province: String,
    city: String,
    area: String,
}

fn find_district_by_code(code: &str) -> Result<String, Box<dyn Error>> {
    // 读取文件内容
    let json_str = fs::read_to_string("area.json")?;
    
    // 解析 JSON
    let districts: Vec<District> = serde_json::from_str(&json_str)?;
    
    // 查找匹配的区域
    let district_name = districts
        .iter()
        .find(|d| d.code == code)
        .map(|d| d.name.clone())
        .unwrap_or_else(|| "未知省份".to_string());
    
    Ok(district_name)
}

fn parse_location(id_card_no: &str) -> String {
    // 前两位
    let province_code = &id_card_no[0..2];
    // 前四位 + 00
    let city_code = format!("{}00", &id_card_no[0..4]);
    // 前六位
    let district_code = &id_card_no[0..6];
    
    // 修改错误处理方式
    let province_name = match find_province_by_code(province_code){
        Ok(name) => name,
        Err(e) => {
            eprintln!("错误: {}", e);  // 打印错误信息到标准错误输出
            "未知省份".to_string()     // 返回默认值
        }
    };

    // 北京、天津、上海、重庆
    let city = if province_code == "11" || province_code == "12" || province_code == "31" || province_code == "50" {
        "市辖区".to_string()
    } else {
        match find_city_by_code(&city_code) {
            Ok(name) => name,
            Err(e) => {
                eprintln!("错误: {}", e);
                "未知城市".to_string()
            }
        }
    };


    let district = match find_district_by_code(district_code) {
        Ok(name) => name,
        Err(e) => {
            eprintln!("错误: {}", e);
            "未知区域".to_string()
        }
    };


    format!("{}-{}-{}", province_name, city, district)
}


// pub fn check_id_card(id_card_no: &str) -> String {
//     // 位权值数组
//     let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
    
//     // 验证输入长度
//     if id_card_no.len() != 18 {
//         return "身份证号码错误".to_string();
//     }

//     // 计算加权和
//     let mut sum = 0;
//     for (i, ch) in id_card_no.chars().enumerate() {
//         if i >= 18 { break; }
        
//         let value = match ch {
//             'x' | 'X' => 10,
//             '0'..='9' => ch.to_digit(10).unwrap() as i32,
//             _ => return "身份证号码错误".to_string()
//         };
        
//         sum += weights[i] * value;
//     }

//     // 判断是否满足条件 (sum % 11 == 1)
//     if sum % 11 == 1 {
//         "身份证号码正确".to_string()
//     } else {
//         "身份证号码错误".to_string()
//     }
// }


